﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using DataAccess;
using MongoDB;

namespace SkynetMongoDBAccess
{
    /// <summary>
    /// 自定义类型 操作
    /// </summary>
    /// <typeparam name="T">自定义类型（class）</typeparam>
    ///<remarks>
    /// 作者：         李志强
    /// 开发时间：  2011-04-18
    /// </remarks>
    public class MongoEntityDB<T> : MongoAbstractDB, IMongoAccess<T> where T : class
    {
        private MongoCollection<T> _mongoCollection;
     
        public MongoEntityDB(string conString,string collectionName)
            : base(conString)
        {
            if (string.IsNullOrEmpty(collectionName))
            {
                CollectionName = typeof(T).Name;
            }
            else
            {
                CollectionName = collectionName;
            }
        }
        public MongoEntityDB(string connection, string collection,long cachelength)
            : base(connection,cachelength)
        {
            CollectionName = collection;
        }

        //获取集合
        private MongoCollection<T> GetMongoCollcetion
        {
            get
            {
                if (_mongoCollection == null)
                {
                    _mongoCollection = base.GetDataBase.GetCollection<T>(CollectionName) as MongoCollection<T>;
                }
                return _mongoCollection;
            }
        }

        //插入数据
        public void Insert(T document)
        {
            GetMongoCollcetion.Insert(document);
        }
        //插入集合
        public void Insert(List<T> list)
        {
            GetMongoCollcetion.Insert<T>(list);
        }
        //保存数据 ,如果不存在则不插入
        public void Save(T document)
        {
            GetMongoCollcetion.Save(document, false);
        }
        //删除指定条件的数据
        public void Delete(Expression<Func<T, bool>> filter)
        {
            GetMongoCollcetion.Remove<T>(filter);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="document">修改后的数据</param>
        /// <param name="filter">条件判断</param>
        public void Modify(T document, Expression<Func<T, bool>> filter)
        {
            //GetMongoCollcetion.FindAndModify(document, FindOne(filter));
            GetMongoCollcetion.Update<T>(document, filter);
        }
        public void ModifyAll(T document, Expression<Func<T, bool>> filter)
        {
            GetMongoCollcetion.UpdateAll<T>(document, filter);
        }
        /// <summary>
        /// 删除所有记录
        /// </summary>
        public void DeleteAll()
        {
            GetMongoCollcetion.Remove(o => true);
        }
        /// <summary>
        /// 超找所有记录
        /// </summary>
        /// <returns></returns>
        public List<T> FindAll()
        {
            List<T> list = GetMongoCollcetion.FindAll().Documents.ToList();
            return list;
        }
        /// <summary>
        /// 查找指定条件的集合
        /// </summary>
        /// <param name="document">条件</param>
        /// <returns></returns>
        public IEnumerable<T> Find(Expression<Func<T, bool>> filter)
        {
            return GetMongoCollcetion.Find<T>(filter).Documents;
        }
    
        /// <summary>
        /// 查找指定条件的集合并分页
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="index">从第几个开始</param>
        /// <param name="count">返回几个元素</param>
        /// <returns></returns>
        public IEnumerable<T> Find(Expression<Func<T, bool>> filter, int index, int count, out int maxCount)
        {
            IQueryable<T> query = GetMongoCollcetion.Linq<T>();
            maxCount = query.Where(filter).Count();
            return query.Where(filter).Skip(index).Take(count).ToList();
        }
        //传统分组查询
        public void GroupBy(string groupName)
        {
            //以groupName 作为键 emit 函数，加入到集合中， 1 表示 累加1操作
            List<Document> list = GetMongoCollcetion.MapReduce()
               .Map(new Code(@"
                    function() {
                        emit(this." + groupName + @",1);
                    }"))
                .Reduce(new Code(@"
                    function(key, values) {
                        var sum = 0;
                        values.forEach(function(prev) {
                            sum += prev;
                        });
                        return sum;
                    }"))
                .Out("MapReduce")
                .Documents.ToList();
            
           
        }
        public IQueryable<T> Query
        {
           get
            {
               return  GetMongoCollcetion.Linq<T>();
            }
        }
        
        /// <summary>
        /// 查找单个记录
        /// </summary>
        /// <param name="document">条件</param>
        /// <returns>如果结果有多条 则返回最后一条记录</returns>
        public T FindOne(Expression<Func<T, bool>> filter)
        {
            return GetMongoCollcetion.FindOne<T>(filter);
        }


        public void dispose()
        {
            base.Dispose();
        }
    }

}
